//////////////////////////////////////////////////////////////////////////
// FileName:ucTrees
// CreateBy:Fenky
// CreateDate:2009-5-27
// Description:
//		
//      
// Modify Log:090812:Update the Context menu display problem --dragon 
//            20100104:Update the Script folder location method of xtreeview.js --DragonXiong
//	
// Copyright:ASL-MIS
/////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Data;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Auto.Web.Common;
using Auto.Data.Security;
using BLL = Auto.Data.Systems.BLL;
using Model = Auto.Data.Systems.Model;

namespace BaseSystem._System.UserControl
{

    public partial class ucTrees : System.Web.UI.UserControl
    {
        private bool _isshowvalue;
        private bool _iscontextmenu;
        private bool _isgetparentvalue;

        public delegate void OperationClickEventHandler(string operation, string value);
        public event OperationClickEventHandler OperationClick;

        public struct TreesData
        {
            public DataTable DT;
            public string RootFieldValue;
            public string RootFieldText;
            public string ParentID;
            public string ChildFieldValue;
            public string ChildFieldText;
        }

        TreesData data;
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                this.loadJs.InnerHtml = string.Format(@"<script type=""text/javascript""  src=""{0}xtreeview.js""></script>", ("../_System/")); //this.loadJs.InnerHtml = string.Format(@"<script type=""text/javascript""  src=""{0}xtreeview.js""></script>", Request.ApplicationPath + ("/_System/"));
            }
        }

        #region Property
        
        public bool IsCheckParentNode
        {
            set
            {
                if (value)
                {
                    this.trRoles.Attributes.Add("onclick", "CheckEvent()");
                }
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is show tree value.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is show tree value; otherwise, <c>false</c>.
        /// </value>
        public bool IsShowTreeValue
        {
            get { return _isshowvalue; }
            set { _isshowvalue = value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is context menu.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is context menu; otherwise, <c>false</c>.
        /// </value>
        public bool IsContextMenu
        {
            get { return _iscontextmenu; }
            set
            {
                _iscontextmenu = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is context menu.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is context menu; otherwise, <c>false</c>.
        /// </value>
        public bool IsGetParentValue
        {
            get { return _isgetparentvalue; }
            set
            {
                _isgetparentvalue = value;
            }
        }

        #endregion Property

        #region Set TreesData
        /// <summary>
        /// Sets the trees data.
        /// </summary>
        /// <param name="dt">The dt.</param>
        /// <param name="rootFieldValue">The root field value.</param>
        /// <param name="rootFieldText">The root field text.</param>
        /// <param name="parentID">The parent ID.</param>
        /// <param name="childFieldValue">The child field value.</param>
        /// <param name="childFieldText">The child field text.</param>
        public void SetTreesData(DataTable dt, string rootFieldValue, string rootFieldText, string parentID, string childFieldValue, string childFieldText)
        {
            data = new TreesData();
            data.ChildFieldText = childFieldText;
            data.ChildFieldValue = childFieldValue;
            data.DT = dt;
            data.ParentID = parentID;
            data.RootFieldText = rootFieldText;
            data.RootFieldValue = rootFieldValue;
        }

        #endregion Set TreesData

        #region Get Value

        /// <summary>
        /// Gets the parent value.
        /// </summary>
        /// <param name="parent">The parent.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        private string GetParentValue(TreeNode parent,string value)
        {
            string result = !string.IsNullOrEmpty(value) ? value : parent.Value;
            if (_isgetparentvalue)
            {
                if (parent.Parent != null)
                {
                    result += "|" + parent.Parent.Value;
                    result = GetParentValue(parent.Parent, result);
                }
            }
            return result.TrimEnd('|');
        }

        /// <summary>
        /// Gets the parent value.
        /// </summary>
        /// <param name="parent">The parent.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        private string GetParentValue(TreeNode parent)
        {
            string result = string.Empty;
            if (_isgetparentvalue)
            {
                result = GetParentValue(parent, result);

            }
            return result;
        }

        /// <summary>
        /// Gets or sets the checked nodes.
        /// </summary>
        /// <value>The checked nodes.</value>
        public IDictionary<string, string> GetCheckedNodes
        {
            get
            {
                IDictionary<string, string> result = new Dictionary<string, string>();

                foreach (TreeNode trChecked in this.trRoles.CheckedNodes)
                {
                    if (trChecked.ChildNodes.Count == 0)
                    {
                        string key = GetParentValue(trChecked, "");
                        if (!result.ContainsKey(key))
                        {
                            result.Add(key, trChecked.Value);
                        }
                    }
                }
                return result;
            }
        }   
        /// <summary>
        /// Gets or sets the checked nodes.
        /// </summary>
        /// <value>The checked nodes.</value>
        public IDictionary<string, string> GetCheckedLeafNodes
        {
            get
            {
                IDictionary<string, string> result = new Dictionary<string, string>();

                foreach (TreeNode trChecked in this.trRoles.CheckedNodes)
                {
                    result.Add(trChecked.Value, trChecked.Value);
                } 
                foreach (TreeNode trChecked in this.trRoles.CheckedNodes)
                {
                    TreeNode temp = trChecked;
                    while (temp.Parent != null)
                    {
                        if (temp.Parent.Checked)
                        {
                            result.Remove(temp.Parent.Value);
                        }
                        temp = temp.Parent;
                    }
                }
                return result;
            }
        }   
        /// <summary>
        /// Gets the context menu.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        private string SetContextMenu(string text, string value, string parentValue)
        {
            string result = string.Empty;
            if (_iscontextmenu)
            {
                result = Server.HtmlDecode(string.Format(@"&lt;span onmousedown=&quot;SetValue(this) &quot; \
                                                            oncontextmenu=&quot;return showmenuie5(event,'{0}') &quot; id='b{0}' &gt;
                                                            {1} {2} &lt;span&gt;", value + (!string.IsNullOrEmpty(parentValue) ? "|" + parentValue : ""),
                                                                               (_isshowvalue ? value + "." : ""), text));
            }
            else
            {
                result = (_isshowvalue ? value + "." : "") + text;
            
            }
            return result;
        }
        #endregion Get Value
        
        #region Clear Checked Node
        /// <summary>
        /// Clears the checked node.
        /// </summary>
        /// <param name="Nds">The NDS.</param>
        private void ClearCheckedNode(TreeNodeCollection Nds)
        {
            foreach (TreeNode node in Nds)
            {
                node.Checked = false;
                ClearCheckedNode(node.ChildNodes);
            }
        }
        #endregion Clear Checked Node

        #region Set Value
        /// <summary>
        /// Sets the checked value.
        /// </summary>
        public void SetCheckedValue()
        {
            ClearCheckedNode(this.trRoles.Nodes);
            this.trRoles.CollapseAll();
            foreach (DataRow dr in data.DT.Rows)
            {
                string rootValue = dr[data.RootFieldValue].ToString();
                string childValue = dr[data.ChildFieldValue].ToString();
                if (!string.IsNullOrEmpty(data.RootFieldText))
                {
                    string[] rootValueArray = rootValue.Split('.');
                    Array.Reverse(rootValueArray);
                    rootValue = childValue + string.Join("", rootValueArray) + dr[data.RootFieldText];
                }
                SetParentCheck(rootValue, childValue);
            }
        }
        /// <summary>
        /// Checks the parent.
        /// </summary>
        /// <param name="rootNodevalue">The root nodevalue.</param>
        /// <param name="childNodeValue">The child node value.</param>
        private void SetParentCheck(string rootNodevalue, string childNodeValue)
        {
            foreach (TreeNode parent in this.trRoles.Nodes)
            {
                SetCheckChild(parent, rootNodevalue, childNodeValue);
            }
        }
        /// <summary>
        /// Checks the child.
        /// </summary>
        /// <param name="parent">The parent.</param>
        /// <param name="rootNodevalue">The root nodevalue.</param>
        /// <param name="childNodeValue">The child node value.</param>
        private void SetCheckChild(TreeNode parent, string rootNodevalue, string childNodeValue)
        {
            foreach (TreeNode child in parent.ChildNodes)
            {
                if (child.Value == childNodeValue)
                {
                    if (GetParentValue(child, child.Value).Replace("|", "") == rootNodevalue || (child.Parent != null && child.Parent.Value == rootNodevalue))
                    {
                        SetParentCheck(child);
                    }
                }
                if (child.ChildNodes.Count > 0)
                {
                    SetCheckChild(child, rootNodevalue, childNodeValue);
                }
            }
        }

        /// <summary>
        /// Sets the parent check.
        /// </summary>
        /// <param name="tn">The tn.</param>
        private void SetParentCheck(TreeNode tn)
        {
            tn.Checked = true;
            if (tn.Parent != null)
            {
                tn.Parent.Checked = true;
                SetParentCheck(tn.Parent);

            }
        }


        public IDictionary<string, string> ContextMenu
        {
            set
            {
                if (value != null && value.Count > 0)
                {
                    string result = string.Empty;
                    foreach (KeyValuePair<string, string> keyValue in value)
                    {
                        result += string.Format(@"<div class=""menuitems"">
                             <a id=""A{0}"" href=""#"" class=""menuitems""  onclick=""Operation('{0}')"" >{1}</a></div> ", keyValue.Key, keyValue.Value);
                    }
                    this.divOper.InnerHtml = result;
                }
            }
        }
        #endregion Set Value

        #region --Trees--

        /// <summary>
        /// Trees the init.
        /// </summary>
        public void TreeInit()
        {
            DataTable dtRoot = data.DT.DefaultView.ToTable(true, new string[] { data.RootFieldText, data.RootFieldValue});
            foreach (DataRow r in dtRoot.Rows)
            {
                TreeNode rootNode = new TreeNode();
                rootNode.Value = r[data.RootFieldValue].ToString();

                rootNode.Text = SetContextMenu(r[data.RootFieldText].ToString(), rootNode.Value, "");
                this.trRoles.Nodes.Add(rootNode);
                TreeInit(rootNode, data);

            }
            this.trRoles.CollapseAll();
        }

        /// <summary>
        /// Trees the init.
        /// </summary>
        public void TreeInitIncludeParent()
        {
            this.trRoles.Nodes.Clear();
            DataTable dtRoot = data.DT.DefaultView.ToTable(true, new string[] { data.RootFieldText, data.RootFieldValue, data.ParentID });
            foreach (DataRow r in dtRoot.Rows)
            {
                if (string.IsNullOrEmpty(r[data.ParentID].ToString()))
                {
                    TreeNode rootNode = new TreeNode();
                    rootNode.Value = r[data.RootFieldValue].ToString();

                    rootNode.Text = SetContextMenu(r[data.RootFieldText].ToString(), rootNode.Value, "");
                    this.trRoles.Nodes.Add(rootNode);

                    TreeInitParent(rootNode, data);
                }
            }
            this.trRoles.CollapseAll();
        } 
        /// <summary>
        /// Trees the init.
        /// </summary>
        /// <param name="rootNode">The root node.</param>
        /// <param name="treesData">The TBL.</param>
        /// <param name="value">The value.</param>
        private void TreeInitParent(TreeNode rootNode, TreesData treesData)
        {

            foreach (DataRow r in treesData.DT.Rows)
            {
                if (rootNode.Value == r[treesData.ParentID].ToString())
                {
                    TreeNode childNode = AddParentNode(rootNode, r[treesData.ChildFieldValue].ToString(), r[treesData.ChildFieldText].ToString());
                    TreeInitChild(childNode, treesData, r[treesData.ChildFieldValue].ToString());
                }
            }
        }
        /// <summary>
        /// Trees the init.
        /// </summary>
        /// <param name="rootNode">The root node.</param>
        /// <param name="treesData">The TBL.</param>
        /// <param name="value">The value.</param>
        private void TreeInit(TreeNode rootNode, TreesData treesData)
        {

            foreach (DataRow r in treesData.DT.Rows)
            {
                if (r[treesData.RootFieldValue].ToString() == rootNode.Value)
                {
                    if (!string.IsNullOrEmpty(treesData.ParentID))
                    {
                        if (r[treesData.ParentID].ToString() == "" )
                        {
                           TreeNode childNode= AddParentNode(rootNode, r[treesData.ChildFieldValue].ToString(), r[treesData.ChildFieldText].ToString());
                            TreeInitChild(childNode, treesData, r[treesData.ChildFieldValue].ToString());
                        }
                    }
                    else
                    {
                        AddParentNode(rootNode, r[treesData.ChildFieldValue].ToString(), r[treesData.ChildFieldText].ToString());
                    }
                }
            }
        }

        /// <summary>
        /// Adds the parent node.
        /// </summary>
        /// <param name="rootNode">The root node.</param>
        /// <param name="value">The value.</param>
        /// <param name="text">The text.</param>
        /// <returns></returns>
        private TreeNode AddParentNode(TreeNode rootNode, string value, string text)
        {
            TreeNode childNode = new TreeNode();
            childNode.Value = value;
            childNode.Text = SetContextMenu(text, value, GetParentValue(rootNode));


            rootNode.ChildNodes.Add(childNode);
            return childNode;
        }

        /// <summary>
        /// Trees the init child.
        /// </summary>
        /// <param name="parentNode">The parent node.</param>
        /// <param name="treesData">The TBL.</param>
        /// <param name="value">The value.</param>
        private void TreeInitChild(TreeNode parentNode, TreesData treesData, string value)
        {
            foreach (DataRow r in treesData.DT.Rows)
            {
                TreeNode childNode = null;
                if (r[treesData.ParentID].ToString() == value)
                {
                    childNode = new TreeNode();
                    childNode.Value = r[treesData.ChildFieldValue].ToString();

                    childNode.Text = SetContextMenu(r[treesData.ChildFieldText].ToString(),
                        childNode.Value, GetParentValue(parentNode));
                                    parentNode.ChildNodes.Add(childNode);
                    TreeInitChild(childNode, treesData, childNode.Value);
                }
            }
        }
        #endregion --Trees--

        #region Event

        protected void lnkOperation_Click(object sender, EventArgs e)
        {
            if (OperationClick != null) { OperationClick(this.hfOperationValue.Value, this.hfValue.Value); }
        }

        #endregion Event

        public TreeNodeTypes ShowCheckBoxes
        {
            set { this.trRoles.ShowCheckBoxes = value; }
        }
     
    }
}